package org.lcc.Service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.lcc.Service.DashboardService;
import org.lcc.Service.FileOssService;
import org.lcc.mapper.DashboardMapper;
import org.lcc.mapper.CertificateTemplateMapper;
import org.lcc.mapper.ExamMapper;
import org.lcc.model.dto.CertificateIssuanceDTO;
import org.lcc.model.dto.CertificateTemplateDTO;
import org.lcc.model.entity.CertificateIssuance;
import org.lcc.model.entity.CertificateTemplate;
import org.lcc.model.entity.Exam;
import org.lcc.model.dto.ExamDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import org.lcc.config.OSSconfig;
import com.alibaba.fastjson.JSON;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.time.LocalDateTime;
import java.util.stream.Collectors;

@Service
public class DashboardServiceImpl implements DashboardService {

    private static final Logger log = LoggerFactory.getLogger(DashboardServiceImpl.class);
    @Autowired
    private DashboardMapper dashboardMapper;

    @Autowired
    private FileOssService fileOssService;

    @Autowired
    private OSSconfig ossConfig;

    @Autowired
    private CertificateTemplateMapper certificateTemplateMapper;

    @Autowired
    private ExamMapper examMapper;

    @Override
    public Map<String, Object> getSystemOverview() {
        Map<String, Object> overview = new HashMap<>();

        // 获取考试总数
        int examCount = dashboardMapper.getExamCount();
        // 获取考生总数
        int studentCount = dashboardMapper.getStudentCount();
        // 获取题库总量
        int questionCount = dashboardMapper.getQuestionCount();
        // 获取已完成考试数
        int completedExamCount = dashboardMapper.getCompletedExamCount();

        overview.put("examCount", examCount);
        overview.put("studentCount", studentCount);
        overview.put("questionCount", questionCount);
        overview.put("completedExamCount", completedExamCount);

        return overview;
    }
    @Override
    public void saveCertificateTemplate(CertificateTemplateDTO templateDTO) throws Exception {
        CertificateTemplate template = new CertificateTemplate();
        template.setTemplateName(templateDTO.getTemplateName());
        
        // 如果有PDF数据，先保存到OSS
        if (templateDTO.getPdfBase64() != null && !templateDTO.getPdfBase64().isEmpty()) {
            byte[] pdfBytes = Base64.getDecoder().decode(templateDTO.getPdfBase64());
            String fileName = "certificate/template/" + UUID.randomUUID().toString() + ".pdf";
            String backgroundPath = fileOssService.uploadPdfToOss(new ByteArrayInputStream(pdfBytes), fileName);
            template.setBackgroundPath(backgroundPath);
        } else {
            template.setBackgroundPath(templateDTO.getBackgroundPath());
        }
        
        // 保存字段配置为JSON字符串
        template.setFieldsConfig(JSON.toJSONString(templateDTO.getFields()));
        template.setCreatorId(templateDTO.getCreatorId());
        
        LocalDateTime now = LocalDateTime.now();
        if (templateDTO.getTemplateId() != null) {
            template.setTemplateId(templateDTO.getTemplateId());
            template.setUpdateTime(now);
            certificateTemplateMapper.updateById(template);
        } else {
            template.setCreateTime(now);
            template.setUpdateTime(now);
            certificateTemplateMapper.insert(template);
        }
    }
    
    @Override
    public List<CertificateTemplateDTO> getTemplatesByCreator(String creatorId) throws Exception {
        // 创建查询条件
        com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<CertificateTemplate> queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
        queryWrapper.eq("creator_id", creatorId);
        queryWrapper.orderByDesc("create_time");
        
        // 查询数据库
        List<CertificateTemplate> templates = certificateTemplateMapper.selectList(queryWrapper);
        
        // 转换为DTO
        List<CertificateTemplateDTO> result = new ArrayList<>();
        for (CertificateTemplate template : templates) {
            CertificateTemplateDTO dto = new CertificateTemplateDTO();
            dto.setTemplateId(template.getTemplateId());
            dto.setTemplateName(template.getTemplateName());
            dto.setBackgroundPath(template.getBackgroundPath());
            dto.setCreatorId(template.getCreatorId());
            dto.setCreateTime(template.getCreateTime());
            dto.setUpdateTime(template.getUpdateTime());
            
            // 解析字段配置
            if (template.getFieldsConfig() != null && !template.getFieldsConfig().isEmpty()) {
                try {
                    List<CertificateTemplateDTO.CertificateField> fields = 
                        JSON.parseArray(template.getFieldsConfig(), CertificateTemplateDTO.CertificateField.class);
                    dto.setFields(fields);
                } catch (Exception e) {
                    log.error("解析字段配置失败", e);
                }
            }
            
            result.add(dto);
        }
        
        return result;
    }
    
    @Override
    @Transactional()
    public void deleteTemplate(Integer templateId) throws Exception {
        // 查询模板信息
        CertificateTemplate template = certificateTemplateMapper.selectById(templateId);
        if (template == null) {
            throw new Exception("证书模板不存在");
        }
        
        // 如果有背景图，从OSS删除
        if (template.getBackgroundPath() != null && !template.getBackgroundPath().isEmpty() && 
            template.getBackgroundPath().startsWith("certificate/template/")) {
            try {
                fileOssService.deleteFileFromOss(template.getBackgroundPath());
            } catch (Exception e) {
                log.error("删除OSS文件失败", e);
                // 继续删除数据库记录，即使OSS删除失败
                certificateTemplateMapper.deleteById(templateId);
            }
        }
        
        // 删除数据库记录
        certificateTemplateMapper.deleteById(templateId);
    }
    
    @Override
    public byte[] generateTemplatePreview(Integer templateId) throws Exception {
        // 查询模板信息
        CertificateTemplate template = certificateTemplateMapper.selectById(templateId);
        if (template == null) {
            throw new Exception("证书模板不存在");
        }
        
        String pdfUrl = template.getBackgroundPath();
        if (pdfUrl == null || pdfUrl.isEmpty()) {
            throw new Exception("证书模板背景不存在");
        }
        
        // 从OSS获取PDF文件
        byte[] pdfBytes;
        if (pdfUrl.startsWith("http")) {
            // 如果是完整URL，直接下载
            URL url = new URL(pdfUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            
            try (InputStream inputStream = connection.getInputStream();
                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                
                pdfBytes = outputStream.toByteArray();
            }
        } else {
            // 如果是OSS路径，通过OSS客户端获取
            String endPoint = ossConfig.getEndPoint().replaceAll("^https?://", "");
            String accessKeyId = ossConfig.getAccessKeyId();
            String accessKeySecret = ossConfig.getAccessKeySecret();
            String bucketName = ossConfig.getBucketName();
            
            OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
            try {
                // 从文件URL获取文件的key
                String fileKey = pdfUrl;
                if (pdfUrl.startsWith("https://" + bucketName + "." + endPoint)) {
                    fileKey = pdfUrl.replace("https://" + bucketName + "." + endPoint + "/", "");
                }
                
                OSSObject ossObject = ossClient.getObject(bucketName, fileKey);
                try (InputStream inputStream = ossObject.getObjectContent();
                     ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                    
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    
                    pdfBytes = outputStream.toByteArray();
                }
            } finally {
                ossClient.shutdown();
            }
        }
        
        // 解析字段配置
        List<CertificateTemplateDTO.CertificateField> fields = null;
        if (template.getFieldsConfig() != null && !template.getFieldsConfig().isEmpty()) {
            try {
                fields = JSON.parseArray(template.getFieldsConfig(), CertificateTemplateDTO.CertificateField.class);
            } catch (Exception e) {
                log.error("解析字段配置失败", e);
            }
        }
        
        // 使用iText渲染字段到PDF
        ByteArrayOutputStream renderedPdfStream = new ByteArrayOutputStream();
        PdfReader reader = new PdfReader(pdfBytes);
        PdfStamper stamper = new PdfStamper(reader, renderedPdfStream);
        
        if (fields != null && !fields.isEmpty()) {
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            
            // 获取第一页
            PdfContentByte canvas = stamper.getOverContent(1);
            
            // PDF页面尺寸（A4默认为595x842点）
            float pdfWidth = reader.getPageSize(1).getWidth();
            float pdfHeight = reader.getPageSize(1).getHeight();
            
            // 渲染每个字段
            for (CertificateTemplateDTO.CertificateField field : fields) {
                // 计算字段位置（百分比转为实际坐标）
                float x = (float) (field.getPercentX() * pdfWidth);
                float y = (float) ((1 - field.getPercentY()) * pdfHeight); // 注意Y坐标是从底部向上的
                
                // 设置字体颜色
                Color color = Color.BLACK;
                if (field.getColor() != null && !field.getColor().isEmpty()) {
                    try {
                        java.awt.Color awtColor = java.awt.Color.decode(field.getColor());
                        color = new Color(awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue());
                    } catch (Exception e) {
                        log.warn("解析颜色失败: " + field.getColor(), e);
                    }
                }
                
                // 设置字体大小和样式
                int fontSize = field.getFontSize() != null ? field.getFontSize() : 12;
                boolean isBold = "bold".equalsIgnoreCase(field.getFontWeight());
                
                // 创建字体
                Font font = new Font(baseFont, fontSize, isBold ? Font.BOLD : Font.NORMAL, new BaseColor(color.getRed(), color.getGreen(), color.getBlue()));
                
                // 开始文本操作
                canvas.beginText();
                canvas.setFontAndSize(baseFont, fontSize);
                canvas.setColorFill(new BaseColor(color.getRed(), color.getGreen(), color.getBlue()));
                
                // 设置文本位置
                canvas.setTextMatrix(x, y);
                
                // 添加文本
                String text = field.getPreviewText() != null ? field.getPreviewText() : field.getLabel();
                canvas.showText(text);
                
                // 结束文本操作
                canvas.endText();
            }
        }
        
        // 关闭资源
        stamper.close();
        reader.close();
        
        // 将渲染后的PDF转换为图像
        byte[] renderedPdfBytes = renderedPdfStream.toByteArray();
        
        // 使用PDFBox将PDF转换为图像
        try (PDDocument document = PDDocument.load(renderedPdfBytes)) {
            PDFRenderer renderer = new PDFRenderer(document);
            
            // 渲染第一页，提高DPI到300以获得更清晰的图像
            BufferedImage image = renderer.renderImageWithDPI(0, 300);
            
            // 将BufferedImage转换为字节数组，使用PNG格式保持高质量
            ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", imageStream);
            
            return imageStream.toByteArray();
        }
    }

    @Override
    public IPage<ExamDto> getFinishedExams(String schoolNumber, Integer current, Integer size) {
        PageHelper.startPage(current, size);
        List<Exam> examList = examMapper.getFinishedExams(schoolNumber);
        PageInfo<Exam> pageInfo = new PageInfo<>(examList);

        // 将实体类列表转为 DTO 列表
        List<ExamDto> dtoList = examList.stream().map(exam -> {
            ExamDto dto = new ExamDto();
            BeanUtils.copyProperties(exam, dto);
            return dto;
        }).collect(Collectors.toList());

        // 构建 MyBatis-Plus 的 Page 对象
        Page<ExamDto> page = new Page<>(current, size, pageInfo.getTotal());
        page.setRecords(dtoList);

        return page;
    }


    @Override
    public ExamDto getExamDetail(Integer examId) {
        // 获取考试基本信息
        Exam exam = examMapper.getExamById(examId);
        if (exam == null) {
            throw new RuntimeException("考试不存在");
        }

        // 转换为DTO
        ExamDto dto = new ExamDto();
        BeanUtils.copyProperties(exam, dto);

        // 获取考试统计数据
        dto.setStudentCount(examMapper.getStudentCount(examId));//学生数量
        dto.setAverageScore(examMapper.getAverageScore(examId));//平均分
        dto.setHighestScore(examMapper.getHighestScore(examId));//最高分
        dto.setLowestScore(examMapper.getLowestScore(examId));//最低分

        return dto;
    }

    @Override
    public List<Map<String, Object>> previewCertificateIssuance(CertificateIssuanceDTO issuanceDTO) throws Exception {
        log.info("开始预览证书颁发，参数: {}", issuanceDTO);
        
        // 1. 获取考试信息
        Exam exam = examMapper.getExamById(issuanceDTO.getExamId());
        if (exam == null) {
            throw new Exception("考试不存在");
        }
        
        // 2. 获取证书模板
        CertificateTemplate template = certificateTemplateMapper.selectById(issuanceDTO.getTemplateId());
        if (template == null) {
            throw new Exception("证书模板不存在");
        }
        
        // 3. 解析模板字段配置
        List<CertificateTemplateDTO.CertificateField> fields = null;
        if (template.getFieldsConfig() != null && !template.getFieldsConfig().isEmpty()) {
            try {
                fields = JSON.parseArray(template.getFieldsConfig(), CertificateTemplateDTO.CertificateField.class);
            } catch (Exception e) {
                log.error("解析字段配置失败", e);
                throw new Exception("解析字段配置失败: " + e.getMessage());
            }
        }
        
        if (fields == null || fields.isEmpty()) {
            throw new Exception("证书模板字段配置为空");
        }
        
        // 4. 获取符合条件的学生列表（成绩大于等于及格分数线）
        List<Map<String, Object>> qualifiedStudents = examMapper.getQualifiedStudents(
                issuanceDTO.getExamId(), issuanceDTO.getPassThreshold());
        
        log.info("符合条件的学生数量: {}", qualifiedStudents.size());
        
        if (qualifiedStudents.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 5. 为每个学生生成预览数据
        List<Map<String, Object>> previewData = new ArrayList<>();
        for (Map<String, Object> student : qualifiedStudents) {
            Map<String, Object> certificateData = new HashMap<>();
            
            // 基本信息
            certificateData.put("studentId", student.get("studentId"));
            certificateData.put("studentName", student.get("studentName"));
            certificateData.put("score", student.get("score"));
            certificateData.put("examName", exam.getExamName());
            certificateData.put("examDate", formatDate(exam.getStartTime()));
            certificateData.put("certificateCode", generateCertificateCode(
                    String.valueOf(student.get("studentId")), issuanceDTO.getExamId()));
            certificateData.put("issuer", issuanceDTO.getIssuer());
            certificateData.put("issueDate", issuanceDTO.getIssueDate());
            certificateData.put("content", issuanceDTO.getContent());
            
            // 预览图URL（这里实际上不生成，只是占位）
            certificateData.put("previewUrl", "预览图将在实际颁发时生成");
            
            previewData.add(certificateData);
        }
        
        log.info("证书预览数据生成完成，共 {} 条", previewData.size());
        return previewData;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Map<String, Object>> issueCertificates(CertificateIssuanceDTO issuanceDTO) throws Exception {
        log.info("开始颁发证书，参数: {}", issuanceDTO);
        
        // 1. 获取考试信息
        Exam exam = examMapper.getExamById(issuanceDTO.getExamId());
        if (exam == null) {
            throw new Exception("考试不存在");
        }
        
        // 2. 获取证书模板
        CertificateTemplate template = certificateTemplateMapper.selectById(issuanceDTO.getTemplateId());
        if (template == null) {
            throw new Exception("证书模板不存在");
        }
        
        // 3. 解析模板字段配置
        List<CertificateTemplateDTO.CertificateField> fields = null;
        if (template.getFieldsConfig() != null && !template.getFieldsConfig().isEmpty()) {
            try {
                fields = JSON.parseArray(template.getFieldsConfig(), CertificateTemplateDTO.CertificateField.class);
            } catch (Exception e) {
                log.error("解析字段配置失败", e);
                throw new Exception("解析字段配置失败: " + e.getMessage());
            }
        }
        
        if (fields == null || fields.isEmpty()) {
            throw new Exception("证书模板字段配置为空");
        }
        
        // 4. 获取符合条件的学生列表（成绩大于等于及格分数线）
        List<Map<String, Object>> qualifiedStudents = examMapper.getQualifiedStudents(
                issuanceDTO.getExamId(), issuanceDTO.getPassThreshold());
        
        log.info("符合条件的学生数量: {}", qualifiedStudents.size());
        
        if (qualifiedStudents.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 5. 为每个学生生成证书并保存
        List<Map<String, Object>> issuedCertificates = new ArrayList<>();
        
        for (Map<String, Object> student : qualifiedStudents) {
            String studentId = String.valueOf(student.get("studentId"));
            String studentName = String.valueOf(student.get("studentName"));
            
            // 生成证书编码
            String certificateCode = generateCertificateCode(studentId, issuanceDTO.getExamId());
            
            // 渲染证书PDF
            byte[] certificatePdfBytes = renderCertificatePdf(
                    template, 
                    fields,
                    studentName,
                    exam.getExamName(),
                    String.valueOf(student.get("score")),
                    formatDate(exam.getStartTime()),
                    certificateCode,
                    issuanceDTO.getIssuer(),
                    issuanceDTO.getIssueDate(),
                    issuanceDTO.getContent()
            );
            
            // 保存PDF到OSS
            String pdfFileName = "certificate/issued/" + certificateCode + ".pdf";
            String pdfUrl = fileOssService.uploadPdfToOss(new ByteArrayInputStream(certificatePdfBytes), pdfFileName);
            
            // 保存证书颁发记录
            CertificateIssuance issuance = new org.lcc.model.entity.CertificateIssuance();
            issuance.setTemplateId(issuanceDTO.getTemplateId());
            issuance.setStudentId(studentId);
            issuance.setStudentName(studentName);
            issuance.setCertificateCode(certificateCode);
            issuance.setIssuer(issuanceDTO.getIssuer());
            issuance.setIssueDate(parseDate(issuanceDTO.getIssueDate()));
            issuance.setContent(issuanceDTO.getContent());
            issuance.setStatus("有效");
            issuance.setExamId(issuanceDTO.getExamId());
            issuance.setCreateTime(LocalDateTime.now());
            issuance.setPdfUrl(pdfUrl);
            
            // 插入数据库
            dashboardMapper.insertCertificateIssuance(issuance);
            
            // 添加到结果列表
            Map<String, Object> certificateData = new HashMap<>();
            certificateData.put("issuanceId", issuance.getIssuanceId());
            certificateData.put("studentId", studentId);
            certificateData.put("studentName", studentName);
            certificateData.put("certificateCode", certificateCode);
            certificateData.put("pdfUrl", pdfUrl);
            
            issuedCertificates.add(certificateData);
        }
        
        log.info("证书颁发完成，共颁发 {} 份证书", issuedCertificates.size());
        return issuedCertificates;
    }

    /**
     * 生成证书编码
     * 
     * @param studentId 学生ID
     * @param examId 考试ID
     * @return 证书编码
     */
    private String generateCertificateCode(String studentId, Integer examId) {
        // 生成格式: C-年月日-考试ID-学生ID-随机数
        String dateStr = LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"));
        String randomStr = String.format("%04d", new java.util.Random().nextInt(10000));
        return "C-" + dateStr + "-" + examId + "-" + studentId + "-" + randomStr;
    }

    /**
     * 渲染证书PDF
     * 
     * @param template 证书模板
     * @param fields 字段配置
     * @param studentName 学生姓名
     * @param examName 考试名称
     * @param score 考试成绩
     * @param examDate 考试日期
     * @param certificateCode 证书编码
     * @param issuer 颁发机构
     * @param issueDate 颁发日期
     * @param content 证书内容
     * @return 渲染后的PDF字节数组
     * @throws Exception 异常
     */
    private byte[] renderCertificatePdf(
            CertificateTemplate template, 
            List<CertificateTemplateDTO.CertificateField> fields,
            String studentName,
            String examName,
            String score,
            String examDate,
            String certificateCode,
            String issuer,
            String issueDate,
            String content) throws Exception {
        
        log.info("开始渲染证书PDF，模板ID: {}, 学生: {}", template.getTemplateId(), studentName);
        
        // 获取模板背景PDF
        String pdfUrl = template.getBackgroundPath();
        if (pdfUrl == null || pdfUrl.isEmpty()) {
            throw new Exception("证书模板背景不存在");
        }
        
        // 从OSS获取PDF文件
        byte[] pdfBytes;
        if (pdfUrl.startsWith("http")) {
            // 如果是完整URL，直接下载
            URL url = new URL(pdfUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            
            try (InputStream inputStream = connection.getInputStream();
                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                
                pdfBytes = outputStream.toByteArray();
            }
        } else {
            // 如果是OSS路径，通过OSS客户端获取
            String endPoint = ossConfig.getEndPoint().replaceAll("^https?://", "");
            String accessKeyId = ossConfig.getAccessKeyId();
            String accessKeySecret = ossConfig.getAccessKeySecret();
            String bucketName = ossConfig.getBucketName();
            
            OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
            try {
                // 从文件URL获取文件的key
                String fileKey = pdfUrl;
                if (pdfUrl.startsWith("https://" + bucketName + "." + endPoint)) {
                    fileKey = pdfUrl.replace("https://" + bucketName + "." + endPoint + "/", "");
                }
                
                OSSObject ossObject = ossClient.getObject(bucketName, fileKey);
                try (InputStream inputStream = ossObject.getObjectContent();
                     ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                    
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    
                    pdfBytes = outputStream.toByteArray();
                }
            } finally {
                ossClient.shutdown();
            }
        }
        
        // 使用iText渲染字段到PDF
        ByteArrayOutputStream renderedPdfStream = new ByteArrayOutputStream();
        PdfReader reader = new PdfReader(pdfBytes);
        PdfStamper stamper = new PdfStamper(reader, renderedPdfStream);
        
        if (fields != null && !fields.isEmpty()) {
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            
            // 获取第一页
            PdfContentByte canvas = stamper.getOverContent(1);
            
            // PDF页面尺寸
            float pdfWidth = reader.getPageSize(1).getWidth();
            float pdfHeight = reader.getPageSize(1).getHeight();
            
            // 渲染每个字段
            for (CertificateTemplateDTO.CertificateField field : fields) {
                // 计算字段位置（百分比转为实际坐标）
                float x = (float) (field.getPercentX() * pdfWidth);
                float y = (float) ((1 - field.getPercentY()) * pdfHeight); // 注意Y坐标是从底部向上的
                
                // 设置字体颜色
                Color color = Color.BLACK;
                if (field.getColor() != null && !field.getColor().isEmpty()) {
                    try {
                        java.awt.Color awtColor = java.awt.Color.decode(field.getColor());
                        color = new Color(awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue());
                    } catch (Exception e) {
                        log.warn("解析颜色失败: " + field.getColor(), e);
                    }
                }
                
                // 设置字体大小和样式
                int fontSize = field.getFontSize() != null ? field.getFontSize() : 12;
                boolean isBold = "bold".equalsIgnoreCase(field.getFontWeight());
                
                // 创建字体
                Font font = new Font(baseFont, fontSize, isBold ? Font.BOLD : Font.NORMAL, 
                        new BaseColor(color.getRed(), color.getGreen(), color.getBlue()));
                
                // 开始文本操作
                canvas.beginText();
                canvas.setFontAndSize(baseFont, fontSize);
                canvas.setColorFill(new BaseColor(color.getRed(), color.getGreen(), color.getBlue()));
                
                // 设置文本位置
                canvas.setTextMatrix(x, y);
                
                // 根据字段类型获取对应的值
                String fieldValue = "";
                String fieldKey = field.getFieldKey().toLowerCase();
                
                if (fieldKey.contains("name") || fieldKey.contains("student") || 
                        field.getLabel().toLowerCase().contains("姓名") || field.getLabel().toLowerCase().contains("名字")) {
                    fieldValue = studentName;
                } else if (fieldKey.contains("exam") || field.getLabel().toLowerCase().contains("考试")) {
                    fieldValue = examName;
                } else if (fieldKey.contains("score") || field.getLabel().toLowerCase().contains("成绩")) {
                    fieldValue = score;
                } else if (fieldKey.contains("date") && fieldKey.contains("exam")) {
                    fieldValue = examDate;
                } else if (fieldKey.contains("code") || field.getLabel().toLowerCase().contains("编号")) {
                    fieldValue = certificateCode;
                } else if (fieldKey.contains("issuer") || field.getLabel().toLowerCase().contains("机构")) {
                    fieldValue = issuer;
                } else if (fieldKey.contains("date") && fieldKey.contains("issue")) {
                    fieldValue = issueDate;
                } else if (fieldKey.contains("content") || field.getLabel().toLowerCase().contains("正文") || 
                        field.getLabel().toLowerCase().contains("内容")) {
                    fieldValue = content;
                }
                
                // 添加文本
                canvas.showText(fieldValue);
                
                // 结束文本操作
                canvas.endText();
            }
        }
        
        // 关闭资源
        stamper.close();
        reader.close();
        
        log.info("证书PDF渲染完成，学生: {}", studentName);
        return renderedPdfStream.toByteArray();
    }

    /**
     * 格式化日期
     * 
     * @param date 日期对象
     * @return 格式化后的日期字符串
     */
    private String formatDate(LocalDateTime date) {
        if (date == null) return "";
        return java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd").format(date);
    }
    /**
     * 解析日期字符串
     * 
     * @param dateStr 日期字符串
     * @return 日期对象
     */
    private Date parseDate(String dateStr) {
        if (dateStr == null || dateStr.isEmpty()) return new Date();
        try {
            return new java.text.SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
        } catch (Exception e) {
            log.error("解析日期失败: " + dateStr, e);
            return new Date();
        }
    }

    @Override
    public IPage<Map<String, Object>> getStudentCertificates(String studentId, Integer pageNum, Integer pageSize, String keyword) throws Exception {
        log.info("获取学生证书列表, studentId: {}, pageNum: {}, pageSize: {}, keyword: {}", 
                studentId, pageNum, pageSize, keyword);
        
        try {
            // 创建分页对象
            Page<Map<String, Object>> page = new Page<>(pageNum, pageSize);
            
            // 查询证书列表
            List<Map<String, Object>> certificates = dashboardMapper.getStudentCertificates(studentId, keyword);
            
            // 处理每个证书记录，添加预览图URL
            for (Map<String, Object> cert : certificates) {
                try {
                    // 获取证书PDF URL
                    String pdfUrl = (String) cert.get("pdfUrl");
                    
                    // 生成预览图URL (这里可以是PDF的第一页预览或专门的预览图)
                    if (pdfUrl != null && !pdfUrl.isEmpty()) {
                        // 可以使用已有的模板预览功能，或者直接使用PDF URL
                        cert.put("previewUrl", pdfUrl);
                    }
                    
                    // 格式化日期显示
                    if (cert.get("issueDate") != null) {
                        Date issueDate = (Date) cert.get("issueDate");
                        cert.put("issueDate", new java.text.SimpleDateFormat("yyyy-MM-dd").format(issueDate));
                    }
                    
                    // 获取考试名称
                    Integer examId = (Integer) cert.get("examId");
                    if (examId != null) {
                        Exam exam = examMapper.getExamById(examId);
                        if (exam != null) {
                            cert.put("examName", exam.getExamName());
                        } else {
                            cert.put("examName", "未知考试");
                        }
                    }
                } catch (Exception e) {
                    log.error("处理证书记录失败", e);
                    // 继续处理下一个证书
                }
            }
            
            // 设置分页数据
            long total = certificates.size();
            
            // 手动分页
            int start = (pageNum - 1) * pageSize;
            int end = Math.min(start + pageSize, certificates.size());
            
            List<Map<String, Object>> pagedCertificates = certificates;
            if (start < end) {
                pagedCertificates = certificates.subList(start, end);
            } else {
                pagedCertificates = new ArrayList<>();
            }
            
            page.setRecords(pagedCertificates);
            page.setTotal(total);
            
            return page;
        } catch (Exception e) {
            log.error("获取学生证书列表失败", e);
            throw new Exception("获取学生证书列表失败: " + e.getMessage());
        }
    }
}